package scenetracer.core.primitive;

import scenetracer.core.Primitive;
import scenetracer.core.Ray;
import scenetracer.core.primitive.IntersectionState.IntersectionKind;
import scenetracer.math.Point2;
import scenetracer.math.Point3;
import scenetracer.math.Vector3;

public class Plane extends Primitive {

	float center;
	Vector3 normal;
	private Vector3 uaxis;
	private Vector3 vaxis;
	
	public Plane(Point3 center, Vector3 normal){		
		this.normal = normal;		
		this.center = -this.normal.dot(center.x, center.y, center.z);
		createAxis();
	}
	
	public Plane(Point3 center, Point3 point1, Point3 point2){
		
		Vector3 firstAxis = Point3.sub(center, point1, new Vector3());
		Vector3 secondAxis = Point3.sub(center, point2, new Vector3());
		
		firstAxis = firstAxis.normalize();
		secondAxis = secondAxis.normalize();
		
		this.normal = Vector3.cross(firstAxis, secondAxis, new Vector3());		
		this.center = -this.normal.dot(center.x, center.y, center.z);
		createAxis();
	}
	
	public void createAxis(){
		uaxis = new Vector3(this.normal.y, this.normal.z, -this.normal.x);
		vaxis = Vector3.cross(uaxis, this.normal);
	}
	
	@Override
	public boolean Intersect(Ray ray, IntersectionState intersection) {
		float det = Vector3.dot(this.normal, ray.getDirection());
		
		if(Math.abs(det)< 0.00001f)
			return false;
				
		Point3 rayOrigin = ray.getOrigin();
		float t = - (this.normal.dot(rayOrigin.x, rayOrigin.y, rayOrigin.z) + center)/ det;
		
		if(t < 0)
			return false;
		
		Point3 intersectionPoint = Point3.add(rayOrigin,
				new Vector3(ray.getDirection()).mul(t),	new Point3());
		intersection.setIntersectionPoint(intersectionPoint);
		intersection.setIntersectionKind(IntersectionKind.OUT);
		intersection.setNormal(getNormal(intersection));
		intersection.setPrimitive(this);
		return true;
	}

	
	@Override
	public Vector3 getNormal(IntersectionState i) {	
		return new Vector3(this.normal);
	}

	@Override
	public Point2 getTextureCoords(Point3 point) {	
				
		float u = Vector3.dot(point.toVector(), uaxis);
		float v = Vector3.dot(point.toVector(), vaxis);
		
		Point2 pointUV = new Point2(u, v);
		
		return pointUV;
	}


}
